package com.sztz.excel;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 导出EasyExcel自适应宽度策略
 * @author yzy
 * @date 2022/8/2 16:26
 */
public class AutoCellWidthStrategy extends AbstractColumnWidthStyleStrategy {
    /**
     * 记录每一列的最大宽度
     */
    private Map<Integer,Integer> columnMaxWidth = new HashMap<>(8);
    /**
     *
     * @param writeSheetHolder sheet处理器
     * @param cellDataList 单元格数据信息
     * @param cell 单元格信息
     * @param head 表头信息
     * @param relativeRowIndex 行号
     * @param isHead 是否是表头
     * @author yzy
     * @date 2022/8/2 17:21
     */
    @Override
    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if( isHead || CollUtil.isNotEmpty(cellDataList)){
            //设置head的单元格宽度
            Integer length = getCellValueLength(cellDataList.get(0), cell, isHead);
            //获取当前单元格所在列设置过的最大宽度
            Integer maxWidth = columnMaxWidth.get(cell.getColumnIndex());
            //是否需要再设置宽度，有可能excel头或前面几行数据就设置过宽度
            boolean canSetWidth = length > 0 && (ObjectUtil.isNull(maxWidth) || length > maxWidth);
            if(canSetWidth){
                columnMaxWidth.put(cell.getColumnIndex(),length);
                writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), length * 256);
            }
        }
    }
    /**
     * 计算出数据的长度
     * @param cellData 单元格数据
     * @param cell 单元格
     * @param isHead 是否是表头
     * @return Integer 数据长度
     * @author yzy
     * @date 2022/8/2 17:21
     */
    private Integer getCellValueLength(CellData cellData, Cell cell, boolean isHead) {
        if (isHead) {
            //头的长度比较好计算
            int length = cell.getStringCellValue().getBytes().length;
            return  length > 255 ? 255 : length;
        }
        //数据的长度需要获取数据类型
        CellDataTypeEnum type = cellData.getType();
        if (ObjectUtil.isNull(type)) {
            return -1;
        }
        switch (type) {
            case STRING:
                return cellData.getStringValue().getBytes().length;
            case BOOLEAN:
                return cellData.getBooleanValue().toString().getBytes().length;
            case NUMBER:
                return cellData.getNumberValue().toString().getBytes().length;
            default:
                return -1;
        }
    }
}
